package com.csvw.skr.notice.service;

import com.csvw.skr.basic.core.JobType;
import com.csvw.skr.notice.entity.NoticeMessage;
import com.csvw.skr.notice.entity.NoticePush;
import com.csvw.skr.notice.entity.NoticeReceiver;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import com.webonn.frame.core.Pagination;
import com.webonn.frame.db.MyDao;
import com.webonn.frame.util.MyStringUtil;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.core.MultivaluedMap;
import java.util.*;

/**
 * Created by Administrator on 2016/9/18.
 */
public class NoticeMessageService {
    @Autowired
    private MyDao dao;

    public Pagination queryNoticeMessages(int start, int limit, MultivaluedMap<String, String> filter) {
        Pagination p = new Pagination();
        p.setStart(start);
        p.setLimit(limit);
        List<Object> paramsList = Lists.newArrayList();

        String sql = "select DISTINCT t_message.pk_id as id, t_message.publishDate, t_message.title, t_message.subtitle, t_user.name as publisherName, t_receiver.readover  from csvw_skr_notice_message t_message " +
                "left join csvw_skr_basic_user t_user on t_user.pk_empno=t_message.publisher " +
                "left join csvw_skr_notice_receiver t_receiver on t_receiver.messageId = t_message.pk_id " +
                "where t_message.active=true %s order by  t_message.updated desc,t_message.publishDate DESC ";
        String term = "";

        String publisher = filter.getFirst("publisher");
        if (!MyStringUtil.isNullOrEmpty(publisher)) {
            term += " and t_message.publisher=?  ";
            paramsList.add(publisher.trim());
        }

        String receiver = filter.getFirst("receiver");
        if (!MyStringUtil.isNullOrEmpty(receiver)) {
            term += " and t_receiver.empno=?  ";
            paramsList.add(receiver.trim());
        }

        if (receiver != null && publisher != null) {
            return new Pagination();
        }

        String search = filter.getFirst("search");
        if (!MyStringUtil.isNullOrEmpty(search)) {
            term += " and CONCAT_WS(',', t_message.title, t_message.subtitle, t_message.content) like ? ";
            paramsList.add("%" + search.trim() + "%");
        }

        String query = String.format(sql, term);
        return dao.queryResultToMapPagination(query, p, paramsList.toArray());
    }

    public NoticeReceiver readNoticeMessage(String receiver, String messageId) {
        NoticeReceiver noticeReceiver = new NoticeReceiver();
        noticeReceiver.setId(messageId + "-" + receiver);
        noticeReceiver.setEmpno(receiver);
        noticeReceiver.setMessageId(messageId);
        noticeReceiver.setReadover(true);
        return dao.persist(noticeReceiver);
    }

    public NoticeMessage addNoticeMessage(NoticeMessage entity) {
        entity.setActive(true);
        entity.setCreated(new Date());
        entity.setUpdated(new Date());
        return dao.persist(entity);
    }

    public NoticeMessage getNoticeMessage(String messageId) {
        return dao.get(messageId, NoticeMessage.class);
    }

    public Map<String, Object> getNoticeMessageInfo(String messageId) {
        String sql = "SELECT notice.*, notice.pk_id as id, u. NAME AS publisherName FROM csvw_skr_notice_message notice LEFT JOIN csvw_skr_basic_user u ON u.pk_empno = notice.publisher WHERE notice.pk_id = ?";
        List<Map<String, Object>> list = dao.queryResultToMap(sql, new Object[]{messageId});

        if (list == null || list.isEmpty())
            return null;

        Map<String, Object> result = list.get(0);
        String fileIdStrs = (String) result.get("files");

        if (MyStringUtil.nonNullOrEmpty(fileIdStrs)) {
            String[] fileIds = fileIdStrs.split(",");
            String file_term = "'" + fileIds[0] + "'";
            for (int i = 1; i < fileIds.length; i++) {
                file_term += ",'" + fileIds[i] + "'";
            }
            String fielSql = "select attachment.pk_id as id, attachment.name from csvw_skr_attachment attachment " +
                    "where attachment.pk_id in (%s)  ";
            List<Map<String, Object>> filesInfo = dao.queryResultToMap(String.format(fielSql, file_term), new Object[]{});
            if (null == filesInfo || filesInfo.size() < 1) {
                filesInfo = Lists.newArrayList();
            }
            result.put("filesInfo", filesInfo);
        } else {
            result.put("filesInfo", Lists.newArrayList());
        }

        return result;

    }

    public NoticeMessage updateNoticeMessage(NoticeMessage noticeMessage) {
        NoticeMessage entity_old = getNoticeMessage(noticeMessage.getId());
        noticeMessage.setCreated(entity_old.getCreated());
        noticeMessage.setActive(entity_old.isActive());
        noticeMessage.setUpdated(new Date());
        return dao.persist(noticeMessage);
    }

    public NoticeMessage deleteNoticeMessage(String messageId) {
        NoticeMessage entity_old = getNoticeMessage(messageId);
        if (Objects.nonNull(entity_old) && entity_old.getPublishDate() == null) {
            return dao.delete(entity_old);
        } else {
            return null;
        }
    }

    /**
     * 得到pc端的message列表
     *
     * @param start
     * @param limit
     * @param filter
     * @return
     */
    public Pagination queryPcNoticeMessages(String queryUser, int start, int limit, MultivaluedMap<String, String> filter) {
        Pagination p = new Pagination();
        p.setStart(start);
        p.setLimit(limit);
        List<Object> paramsList = Lists.newArrayList();

        String sql = "SELECT DISTINCT t_message.pk_id AS id,t_message.publishDate,t_message.title,t_message.subtitle,t_message.created,t_message.updated,t_message.`status`,t_user. NAME AS publisherName " +
                "FROM csvw_skr_notice_message t_message " +
                "LEFT JOIN csvw_skr_basic_user t_user ON t_user.pk_empno = t_message.publisher " +
                "LEFT JOIN csvw_skr_notice_receiver t_receiver ON t_receiver.messageId = t_message.pk_id " +
                "WHERE t_message.active = TRUE  %s  ORDER BY t_message.updated DESC,t_message.publishDate DESC";

        String term = "";

        if (!MyStringUtil.isNullOrEmpty(queryUser)) {
            term += "  AND (t_message.publisher = ? OR t_receiver.empno = ? ) ";
            paramsList.add(queryUser);
            paramsList.add(queryUser);
        }

        String search = filter.getFirst("search");
        if (!MyStringUtil.isNullOrEmpty(search)) {
            term += " and CONCAT_WS(',', t_message.title, t_message.subtitle, t_message.content) like ? ";
            paramsList.add("%" + search.trim() + "%");
        }
        String query = String.format(sql, term);

        return dao.queryResultToMapPagination(query, p, paramsList.toArray());
    }

    /**
     * 通知发布
     *
     * @param messageId
     * @param orgIds
     * @return
     */
    public NoticeMessage addNoticeReceiver(String messageId, List<String> orgIds) {
        if (Objects.isNull(orgIds) || orgIds.isEmpty()) return null;

        NoticeMessage noticeMessage = this.getNoticeMessage(messageId);
        List<NoticeReceiver> noticeReceivers = Lists.newArrayList();

        List<NoticePush> noticePushs = Lists.newArrayList();

        String orgsql = "SELECT pk_code FROM csvw_skr_basic_organization WHERE active = TRUE AND ";
        String orgSearchSql = "(";
        for (String orgId : orgIds) {
            orgSearchSql += "pk_code like " + "'%" + orgId + "%' OR ";
        }
        orgSearchSql += ")";
        orgSearchSql = orgSearchSql.replace("OR )", ")");
        orgIds = dao.listIds(orgsql + orgSearchSql, new Object[]{});

        String sql = "SELECT t_user.pk_empno FROM csvw_skr_basic_user t_user WHERE t_user.organization = ?";
        List<String> empnos = Lists.newArrayList();
        orgIds.forEach(orgId -> {
            empnos.addAll(dao.listIds(sql, new Object[]{orgId}));
        });
        // 发布通知时发一份给自己
        if (!empnos.contains(noticeMessage.getPublisher())) empnos.add(noticeMessage.getPublisher());
        empnos.forEach(empno -> {
            noticePushs.add(buildNoticePush(noticeMessage, empno));
            noticeReceivers.add(new NoticeReceiver(messageId + "-" + empno, messageId, empno));
        });

        dao.addBentch(noticeReceivers);
        dao.addBentch(noticePushs);
        noticeMessage.setPublishDate(new Date());
        noticeMessage.setStatus(41);

        return this.updateNoticeMessage(noticeMessage);
    }

    public NoticeMessage addNoticeReceiver(String messageId, Map<String, Set> map) {
        if (Objects.isNull(map) || map.isEmpty()) return null;

        NoticeMessage noticeMessage = this.getNoticeMessage(messageId);
        List<NoticeReceiver> noticeReceivers = Lists.newArrayList();
        List<NoticePush> noticePushs = Lists.newArrayList();
        Set<String> empnos = Sets.newHashSet();

        Set<String> level1 = map.get("level1");
        Set<Map<String, String>> level2 = map.get("level2");
        Set<String> level3 = map.get("level3");

        if (level1 != null || !level1.isEmpty()) {
            String orgSerarh = "";
            for (String org : level1) {
                if (!"SK".equals(org)) org = "'%" + org + "%'";
                else org = "'" + org + "'";
                orgSerarh += "u.organization LIKE " + org + " OR ";
            }
            orgSerarh = orgSerarh.endsWith("OR ") ? orgSerarh.substring(0, orgSerarh.length() - 3) : orgSerarh;
            String sql = "SELECT u.pk_empno AS uId FROM csvw_skr_basic_user u WHERE (%s) and u.active = true ";
            List<String> userList = dao.listIds(String.format(sql, orgSerarh), new Object[]{});
            if (userList != null) empnos.addAll(userList);

        }
        if (level2 != null && !level2.isEmpty()) {
            String searchsql = "";
            for (Map<String, String> level2Map : level2) {
                String org = level2Map.getOrDefault("org", "null");
                String job = level2Map.getOrDefault("job", "null");

                searchsql += "(u.organization LIKE '%" + org + "%' AND u.job = " + job + ") OR ";
            }
            searchsql = searchsql.endsWith("OR ") ? searchsql.substring(0, searchsql.length() - 3) : searchsql;
            String sql = "SELECT u.pk_empno AS uId FROM csvw_skr_basic_user u WHERE (%s) AND u.active = true ";
            List<String> userList = dao.listIds(String.format(sql, searchsql), new Object[]{});
            if (userList != null) empnos.addAll(userList);
        }
        if (level3 != null) {
            empnos.addAll(level3);
        }

        // 发布通知时发一份给自己
        empnos.add(noticeMessage.getPublisher());

        empnos.forEach(empno -> {
            noticePushs.add(buildNoticePush(noticeMessage, empno));
            noticeReceivers.add(new NoticeReceiver(messageId + "-" + empno, messageId, empno));
        });

        dao.addBentch(noticeReceivers);
        dao.addBentch(noticePushs);
        noticeMessage.setPublishDate(new Date());
        noticeMessage.setStatus(41);

        return this.updateNoticeMessage(noticeMessage);
    }

    private NoticePush buildNoticePush(NoticeMessage noticeMessage, String empno) {
        NoticePush noticePush = new NoticePush();
        noticePush.setTitle(noticeMessage.getTitle());
        noticePush.setContent(noticeMessage.getSubtitle());
        noticePush.setCreated(new Date());
        noticePush.setObjectId(noticeMessage.getId());
        noticePush.setReceiver(empno);
        noticePush.setType("PolicyNotice");
        return noticePush;
    }

    public List<Map<String, Object>> queryTreeFirst() {
        String sql = "SELECT org.`name` as 'text',org.pk_code as 'org', 1 as 'level'  " +
                "FROM csvw_skr_basic_organization org " +
                "WHERE (org.pk_code = 'SK' OR (org.pcode = 'SK' AND org.pk_code LIKE '%SKR%')) AND active = TRUE";

        List<Map<String, Object>> first = dao.queryResultToMap(sql, new Object[]{});

        for (Map<String, Object> map : first) {
            map.put("nodes", Lists.newArrayList());
        }
        return first;
    }

    public List<Map<String, Object>> queryTreeSecond(String org, String job) {
        String sql = "SELECT j.`name` as 'text',u.job,? as 'org', 2 as 'level' FROM `csvw_skr_basic_user` u " +
                "LEFT JOIN csvw_skr_basic_job j on j.pk_code = u.job " +
                "WHERE u.organization like ? AND u.pk_empno != 'admin' AND u.active = TRUE %s " +
                "GROUP BY u.job";

        String orgSearch = org;
        if (!"SK".equals(org)) {
            orgSearch = "%" + org + "%";
        }

        if (JobType.MARKETING_VICE_MANAGER.equals(job)) {
            sql = String.format(sql, "and u.job = " + JobType.MARKETING_MANAGER);
        } else {
            sql = String.format(sql, "");
        }

        List<Map<String, Object>> first = dao.queryResultToMap(sql, new Object[]{org, orgSearch});

        for (Map<String, Object> map : first) {
            map.put("nodes", Lists.newArrayList());
        }
        return first;
    }

    public List<Map<String, Object>> queryTreeThird(String org, String job) {
        String sql = "SELECT CONCAT(u.`name`,'(',org.`name`,')') as text, org.`name` as orgName,u.`name` as uName , " +
                "u.pk_empno as uId,? as 'org',? as 'job', 3 as 'level' FROM csvw_skr_basic_user u " +
                "LEFT JOIN csvw_skr_basic_organization org on org.pk_code = u.organization " +
                "WHERE u.organization LIKE ? and u.job = ? ";

        String orgSearch = "%" + org + "%";

        return dao.queryResultToMap(sql, new Object[]{org, job, orgSearch, job});
    }

    public Map<String, Object> getNoticeReadoverCount(String userId) {
        Map<String, Object> result = Maps.newHashMap();
        String sql = "SELECT COUNT(DISTINCT t_message.pk_id) as count FROM csvw_skr_notice_message t_message " +
                "LEFT JOIN csvw_skr_notice_receiver t_receiver ON t_receiver.messageId = t_message.pk_id " +
                "WHERE t_message.active = TRUE AND t_receiver.empno = ? AND t_receiver.readover = FALSE";
        List<Map<String, Object>> list = dao.queryResultToMap(sql, new Object[]{userId});
        if (!Objects.isNull(list) && list.size() > 0) {
            result = list.get(0);
        } else {
            result.put("count", 0);
        }
        return result;
    }
}
